import logging
import os

from ocup.boot import Boot
from ocup.constants import OCUP_LOCK
from ocup.database import db
from ocup.dnf.dnf_manager import DnfManager
from ocup.errors import UnSupport, ForkFail
from ocup.systemd import Service
from ocup.systeminfo import SystemInfo
from ocup.utils import fix_db_path, fix_db_macro, rebuild_db, touch, notify_success, notify_upgrade

logger = logging.getLogger("ocup")


class Ocup(object):

    def __init__(self):
        self.repos = None
        self.system = SystemInfo()
        self.dnf = DnfManager()
        self.service = Service()

    def run(self):
        try:
            touch(OCUP_LOCK)
            self._run()
        except Exception as e:
            logger.error(e)
            db.set("status", "failed")
        finally:
            os.remove(OCUP_LOCK)

    def start(self):
        try:
            pid = os.fork()
        except OSError:
            logger.error("start ocup daemon failed")
            raise ForkFail()
        if pid == 0:
            try:
                touch(OCUP_LOCK)
                self._run()
                notify_success()
            except Exception as e:
                logger.error(e)
                db.set("status", "failed")
            finally:
                os.remove(OCUP_LOCK)
        else:
            notify_upgrade()

    def status(self):
        status = db.get("status")
        if status is None:
            logger.info("status is \"not running\"")
        else:
            logger.info("status is \"{}\"".format(status))
            if status == "success":
                if not os.uname().release.startswith("6"):
                    self._print_success()

    def _run(self):
        db.set("status", "running")
        logger.info("collect system information")
        self.system.resolve_system_info()
        logger.info("checking os version")
        if self.system.name != "OpenCloudOS" or not self.system.version.startswith("8"):
            logger.error("not supported {}-{}".format(self.system.name, self.system.version))
            raise UnSupport()
        else:
            logger.info("upgrade {}-{}".format(self.system.name, self.system.version))
        logger.info("prepare environment")
        logger.info("disable selinux")
        self.system.disable_selinux()
        logger.info("fix local db")
        fix_db_path()
        fix_db_macro()
        logger.info("stop  unimportant services")
        self.service.stop()
        logger.info("clean dnf cache")
        self.dnf.clean_cache()
        logger.info("reset modules")
        self.dnf.disable_modules()
        logger.info("install oc9 release")
        self.dnf.install_oc9_release()
        logger.info("upgrade oc9 pkgs")
        self.dnf.upgrade()
        # logger.info("remove extras pkgs")
        # self.dnf.remove_extras_pkg()
        logger.info("restore system config")
        self.system.restore_system_config()
        logger.info("rebuild rpmdb")
        rebuild_db()
        logger.info("fix grub")
        Boot().fix_grub()
        db.set("status", "success")
        self._print_success()

    @staticmethod
    def _print_success():
        logger.info("####################################################")
        logger.info("#                                                  #")
        logger.info("# upgrade OpenCloud OS success                     #")
        logger.info("# Please reboot the machine to boot OpenCloud OS 9 #")
        logger.info("#                                                  #")
        logger.info("####################################################")
